/*
 * Copyright (C) 2008 Universidade Federal de Campina Grande
 *  
 * This file is part of OurGrid. 
 *
 * OurGrid is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free 
 * Software Foundation, either version 3 of the License, or (at your option) 
 * any later version. 
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details. 
 * 
 * You should have received a copy of the GNU Lesser General Public License 
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package org.ourgrid.peer.controller.ds;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.ourgrid.common.interfaces.DiscoveryService;
import org.ourgrid.common.interfaces.DiscoveryServiceClient;
import org.ourgrid.peer.PeerConfiguration;
import org.ourgrid.peer.PeerConstants;
import org.ourgrid.peer.dao.DiscoveryServiceClientDAO;

import br.edu.ufcg.lsd.commune.api.FailureNotification;
import br.edu.ufcg.lsd.commune.api.InvokeOnDeploy;
import br.edu.ufcg.lsd.commune.api.RecoveryNotification;
import br.edu.ufcg.lsd.commune.container.servicemanager.ServiceManager;
import br.edu.ufcg.lsd.commune.identification.DeploymentID;
import br.edu.ufcg.lsd.commune.identification.ServiceID;

/**
 *
 */
public class DiscoveryServiceNotificationController  {

	private ServiceManager serviceManager;

	@SuppressWarnings("unused")
	@InvokeOnDeploy
	public void init(ServiceManager serviceManager) {
		this.serviceManager = serviceManager;
	}

	@FailureNotification
	public void doNotifyFailure(DiscoveryService monitorable, DeploymentID deploymentID) {

		DiscoveryServiceClientDAO dao = serviceManager.getDAO(DiscoveryServiceClientDAO.class);
		dao.removeDiscoveryService(deploymentID.getServiceID(), serviceManager);
		
		if (dao.IsAliveDsListEmpty()) {
			Future<?> advertActionFuture = dao.getAdvertActionFuture();
			if (advertActionFuture != null) {
				advertActionFuture.cancel(true);
			}
		}
		
		serviceManager.release(monitorable);
		
		for (ServiceID dsId : dao.getDsIDs()) {
			serviceManager.registerInterest(PeerConstants.DS_MONITOR_OBJECT_NAME, dsId.toString(), 
					DiscoveryService.class);
		}
	}
	
	@RecoveryNotification
	public void doNotifyRecovery(DiscoveryService monitorableStub, DeploymentID monitorableId) {

		DiscoveryServiceClientDAO dao = serviceManager.getDAO(DiscoveryServiceClientDAO.class);
		
		boolean listWasEmpty = dao.IsAliveDsListEmpty();
		
		boolean listIsFull = dao.addDiscoveryService(monitorableStub, monitorableId.getServiceID());
		
		DiscoveryServiceClient dsClient = (DiscoveryServiceClient) serviceManager.getObjectDeployment(
				PeerConstants.DS_CLIENT).getObject();
		
		monitorableStub.getRemoteWorkerProviders(dsClient);
		
		if (listWasEmpty) {
			Future<?> advertActionFuture = serviceManager.scheduleActionWithFixedDelay(
					PeerConstants.DS_ACTION_NAME, 
					serviceManager.getContainerContext().parseIntegerProperty(
							PeerConfiguration.PROP_DS_UPDATE_INTERVAL), 
							TimeUnit.SECONDS);
			
			dao.setAdvertActionFuture(advertActionFuture);
		}
		
		if (listIsFull) {
			for (ServiceID dsId : dao.getDsIDs()) {
				if (!dsId.equals(monitorableId.getServiceID()) && !dao.isDsAlive(dsId)) {
					DiscoveryService ds = (DiscoveryService) serviceManager.getStub(dsId, DiscoveryService.class);
					serviceManager.release(ds);
				}
			}
		}
		
	}
	
}
